<?php


namespace EchoPHP\File;

use EchoPHP\Facades\File as FileSystem;
use EchoPHP\File\Exception\FileException;
use Symfony\Component\Mime\MimeTypes;

class File extends \SplFileInfo {

    public function __construct(string $path, bool $checkPath = true) {
        if ($checkPath && !is_file($path)) {
            throw new \Exception('file ' . $path . ' does not exist');
        }
        parent::__construct($path);
    }

    /**
     * 获取文件名
     * @param $name
     * @return bool|mixed|string
     */
    protected function getName($name) {
        $originalName = str_replace('\\', '/', $name);
        $pos = strrpos($originalName, '/');
        $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1);

        return $originalName;
    }

    /**
     * 获取文件mime信息
     * @return mixed
     */
    public function getMimeType() {
        return MimeTypes::getDefault()->guessMimeType($this->getPathname());
    }

    /**
     * 获取文件类型
     * @return |null
     */
    public function guessExtension() {
        return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null;
    }

    /**
     * 文件移动,采用rename方式进行移动
     * @param $directory
     * @param null $name
     * @return File
     * @throws \Exception
     */
    public function move($directory, $name = null) {
        $target = $this->getTargetFile($directory, $name);

        set_error_handler(function ($type, $msg) use (&$error) {
            $error = $msg;
        });
        $renamed = rename($this->getPathname(), $target);
        restore_error_handler();

        if (!$renamed) {
            throw new FileException(sprintf('无法将文件 "%s" 移动到 "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
        }

        @chmod($target, 0666 & ~umask());

        return $target;
    }

    /**
     * 文件复制
     * @param $directory
     * @param null $name
     * @return File
     * @throws \Exception
     */
    public function copy($directory, $name = null) {
        $target = $this->getTargetFile($directory, $name);

        set_error_handler(function ($type, $msg) use (&$error) {
            $error = $msg;
        });
        $copied = copy($this->getPathname(), $target);
        restore_error_handler();

        if (!$copied) {
            throw new FileException(sprintf('无法将文件 "%s" 复制到 "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
        }

        @chmod($target, 0666 & ~umask());

        return $target;
    }

    /**
     * 获取目标文件
     * @param $directory
     * @param null $name
     * @return File
     * @throws \Exception
     */
    protected function getTargetFile($directory, $name = null) {
        if (!is_dir($directory)) {
            if (false === FileSystem::makeDirectory($directory, 0777, true) && !is_dir($directory)) {
                throw new FileException(sprintf('无法创建"%s"', $directory));
            }
        } elseif (!is_writable($directory)) {
            throw new FileException(sprintf('目录"%s"没有写权限', $directory));
        }

        $target = rtrim($directory, '/\\') . DIRECTORY_SEPARATOR . (null === $name ? $this->getBasename() : $this->getName($name));

        return new self($target, false);
    }
}